﻿using System;
using System.Collections.Generic;
using Transformable_Engine_v2.Engine.GameObjects;
using Transformable_Engine_v2.Engine.Global;
using Transformable_Engine_v2.Engine.Time;

namespace Transformable_Engine_v2.Engine.Animation
{
    public abstract class BaseAnimation : IAnimation, IUnloadable
    {
        private Timer _delayTimer;
        protected Timer DurationTimer;

        private List<Timer> _timers;

        private readonly bool _autoStart;

        public bool IsLooping { get; protected set; }
        public bool IsStarted { get; protected set; }

        /// <summary>
        /// Creates a new instance of BaseAnimation
        /// </summary>
        /// <param name="duration">Duration of the animation</param>
        /// <param name="isLooping">Does the animation loop?</param>
        /// <param name="delay">Delay before beginning the animation</param>
        /// <param name="autoStart">Automatically start the animation when it is constructed?</param>
        protected BaseAnimation(double duration, bool isLooping, double delay, bool autoStart)
        {
            _timers = new List<Timer>();

            IsLooping = isLooping;
            IsStarted = false;

            _isAlive = true;

            TotalDuration = delay + duration;

            if (delay > 0)
            {
                _delayTimer = new Timer(delay, false, DelayEnd);
                AddTimers(_delayTimer);
            }
                

            if(duration <= 0)
                Log.LogDebug("Timer initialized with duration <= 0");

            if (duration > 0)
            {
                DurationTimer = new Timer(duration, IsLooping, DurationEnd);
                AddTimers(DurationTimer);
            }
                
            

            _autoStart = autoStart;
        }

        public double TotalDuration { get; private set; }

        /// <summary>
        /// Start the animation
        /// </summary>
        public void Start()
        {
            if(_delayTimer != null)
                _delayTimer.Start();
            else 
                DelayEnd();
            
        }

        public void AddTimers(params Timer[] timer)
        {
            _timers.AddRange(timer);
        }

        /// <summary>
        /// Method called when the animation has ended
        /// </summary>
        protected virtual void DurationEnd()
        {
            if (!IsLooping) 
            {
                Die();
            }
        }

        /// <summary>
        /// Method called when the delay has ended
        /// </summary>
        protected virtual void DelayEnd()
        {
            IsStarted = true;

            if(DurationTimer != null)
                DurationTimer.Start();
        }

        private bool _isAlive;
        public bool IsAlive()
        {
            return _isAlive;
        }

        /// <summary>
        /// Kills the animation by stopping every timer
        /// </summary>
        public virtual void Die()
        {
            _isAlive = false;

            if (DurationTimer != null)
                DurationTimer.Stop();
            if (_delayTimer != null)
                _delayTimer.Stop();
        }

        public virtual void Initialize()
        {
            if(_autoStart)
                Start();
            
        }

        public abstract void Update(TimeSpan gameTime);

        public virtual void FixedStepUpdate(TimeSpan gameTime)
        {
            for (int i = 0; i < _timers.Count; i++)
            {
                _timers[i].FixedStepUpdate(gameTime);
            }
        }

        public virtual void Reset()
        {
            _isAlive = true;

            Start();
        }

        public virtual void UnloadContent()
        {
        }

        public virtual void Stop()
        {
            if (_delayTimer != null)
                _delayTimer.Stop();

            if (DurationTimer != null)
                DurationTimer.Stop();
        }
    }
}